<template>
  <el-drawer
    v-model="visible"
    title="版本管理"
    size="85%"
    @close="handleClose"
  >
    <doc-alert v-if="false" title="工作流手册" url="https://doc.iocoder.cn/bpm/" />

    <ContentWrap>
      <el-table v-loading="loading" :data="list">
        <el-table-column v-if="false" label="定义编号" align="center" prop="id" min-width="250" />
        <el-table-column label="流程名称" align="center" prop="name" width="120" />
        <el-table-column label="流程标识" align="center" prop="key" width="120" />
        <el-table-column label="流程分类" align="center" prop="category" width="120" />
        <el-table-column v-if="false" label="流程图标" align="center" min-width="100">
          <template #default="{ row }">
            <el-image v-if="row.icon" :src="row.icon" class="h-24px w-24pxrounded" />
          </template>
        </el-table-column>
        <el-table-column v-if="false" label="可见范围" align="center" prop="startUserIds" min-width="100">
          <template #default="{ row }">
            <el-text v-if="!row.startUsers?.length"> 全部可见 </el-text>
            <el-text v-else-if="row.startUsers.length === 1">
              {{ row.startUsers[0].nickname }}
            </el-text>
            <el-text v-else>
              <el-tooltip
                class="box-item"
                effect="dark"
                placement="top"
                :content="row.startUsers.map((user: any) => user.nickname).join('、')"
              >
                {{ row.startUsers[0].nickname }}等 {{ row.startUsers.length }} 人可见
              </el-tooltip>
            </el-text>
          </template>
        </el-table-column>
        <el-table-column label="流程类型" align="center" prop="modelType" min-width="120">
          <template #default="{ row }">
            <dict-tag :value="row.modelType" :type="DICT_TYPE.BPM_MODEL_TYPE" />
          </template>
        </el-table-column>
        <el-table-column label="表单信息" align="center" prop="formType" min-width="150">
          <template #default="scope">
            <el-button
              v-if="scope.row.formType === BpmModelFormType.NORMAL"
              type="primary"
              link
              @click="handleFormDetail(scope.row)"
            >
              <span>{{ scope.row.formName }}</span>
            </el-button>
            <el-button
              v-else-if="scope.row.formType === BpmModelFormType.CUSTOM"
              type="primary"
              link
              @click="handleFormDetail(scope.row)"
            >
              <span>{{ scope.row.formCustomCreatePath }}</span>
            </el-button>
            <label v-else>暂无表单</label>
          </template>
        </el-table-column>
        <el-table-column label="流程版本" align="center" min-width="80">
          <template #default="scope">
            <el-tag>v{{ scope.row.version }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="主版本" align="center" min-width="80">
          <template #default="scope">
            <el-tag type="success" v-if="processDefinitionId === scope.row.id">是</el-tag>
            <el-tag type="danger" v-else>否</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="激活状态" align="center" min-width="80">
          <template #default="scope">
            <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
            <el-tag type="danger" v-else>挂起</el-tag>
          </template>
        </el-table-column>

        <el-table-column
          label="部署时间"
          align="center"
          prop="deploymentTime"
          width="180"
          :formatter="dateFormatter"
        />
        <el-table-column label="操作" width="220" align="center" fixed="right">
          <template #default="scope">
            <el-button
              link
              type="primary"
              @click="handleToggleState(scope.row)"
              v-hasPermi="['bpm:process-definition:toggle-state']"
            >
              {{ scope.row.suspensionState === 1 ? '挂起' : '激活' }}
            </el-button>
            <el-button
              link
              type="primary"
              @click="handleDiagramOpen(scope.row)"
            >
              流程图
            </el-button>
            <el-button
              link
              type="primary"
              :disabled="scope.row.id === processDefinitionId"
              @click="handleToggleVersion(scope.row)"
              v-hasPermi="['bpm:process-definition:toggle-version']"
            >
              设为主版本
            </el-button>
            <el-button
              v-if="false"
              link
              type="primary"
              @click="openModelForm(scope.row.id)"
              v-hasPermi="['bpm:model:update']"
            >
              恢复
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <Pagination
        :total="total"
        v-model:page="queryParams.pageNo"
        v-model:limit="queryParams.pageSize"
        @pagination="getList"
      />
    </ContentWrap>

    <!-- 弹窗：表单详情 -->
    <Dialog title="表单详情" v-model="formDetailVisible" width="800">
      <form-create :rule="formDetailPreview.rule" :option="formDetailPreview.option" />
    </Dialog>

    <Dialog title="流程图" v-model="diagramVisible" width="1000">
      <div class="diagram">
        <ProcessInstanceSimpleViewer
          v-show="modelType === BpmModelType.SIMPLE"
          :loading="diagramLoading"
          :model-view="diagramModelView"
        />
        <ProcessInstanceBpmnViewer
          v-show="modelType === BpmModelType.BPMN"
          :loading="diagramLoading"
          :model-view="diagramModelView"
        />
      </div>
    </Dialog>
  </el-drawer>
</template>

<script lang="ts" setup>
import { dateFormatter } from '@/utils/formatTime'
import * as DefinitionApi from '@/api/bpm/definition'
import { setConfAndFields2 } from '@/utils/formCreate'
import { DICT_TYPE } from '@/utils/dict'
import {BpmModelFormType, BpmModelType} from '@/utils/constants'
import ProcessInstanceSimpleViewer
  from "@/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue";
import ProcessInstanceBpmnViewer
  from "@/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue";
import * as ProcessInstanceApi from "@/api/bpm/processInstance";

defineOptions({ name: 'BpmProcessDefinition' })

const emit = defineEmits<{
  (e: 'close'): void
}>()

const message = useMessage() // 消息弹窗
const { push } = useRouter() // 路由
const { query } = useRoute() // 查询参数

const modelId = ref(String)
const modelType = ref(Number)
const processDefinitionId = ref(String)
const diagramVisible = ref(false)
const diagramLoading = ref(false)
const diagramModelView = ref<any>({}) // 流程模型视图
const visible = ref(false)
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  key: undefined
})

const open = (payload?: { modelId: string, modelKey: string, processDefinitionId: string }) => {
  visible.value = true
  if (payload) {
    modelId.value = payload?.modelId
    processDefinitionId.value = payload?.processDefinitionId
    queryParams.key = payload?.modelKey
  }
  queryParams.pageNo = 1
  getList()
}

/** 查询列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await DefinitionApi.getProcessDefinitionPage(queryParams)
    list.value = data.list
    total.value = data.total
  } finally {
    loading.value = false
  }
}

/** 流程表单的详情按钮操作 */
const formDetailVisible = ref(false)
const formDetailPreview = ref({
  rule: [],
  option: {}
})
const handleFormDetail = async (row: any) => {
  if (row.formType == BpmModelFormType.NORMAL) {
    // 设置表单
    setConfAndFields2(formDetailPreview, row.formConf, row.formFields)
    // 弹窗打开
    formDetailVisible.value = true
  } else {
    await push({
      path: row.formCustomCreatePath
    })
  }
}

const handleToggleState = async (row: any) => {
  const state = row.suspensionState
  const newState = state === 1 ? 2 : 1
  try {
    // 修改状态的二次确认
    const id = row.id
    const statusState = state === 1 ? '挂起' : '激活'
    const content = '是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?'
    await message.confirm(content)
    // 发起修改状态
    await DefinitionApi.toggleState(id, newState)
    message.success(statusState + '成功')
    // 刷新列表
    getList()
  } catch {}
}

const handleDiagramOpen = async (row: any) => {
  diagramVisible.value = true
  modelType.value = row.modelType
  if (BpmModelType.BPMN === row.modelType) {
    // 重置，解决 BPMN 流程图刷新不会重新渲染问题
    diagramModelView.value = {
      bpmnXml: ''
    }
  }
  const data = await DefinitionApi.getBpmnModelView(row.id)
  if (data) {
    diagramModelView.value = data
  }
}

const handleToggleVersion = async (row: any) => {
  try {
    // 修改状态的二次确认
    const id = row.id
    const content = '是否确认设置' + row.version + '为主版本吗?'
    await message.confirm(content)
    // 发起修改状态
    processDefinitionId.value = await DefinitionApi.toggleVersion(id, modelId.value)
    message.success('设置成功')
    // 刷新列表
    getList()
  } catch {}
}

/** 恢复流程模型弹窗 */
const openModelForm = async (id?: number) => {
  await push({
    name: 'BpmModelUpdate',
    params: { id, type: 'definition' }
  })
}

/** 关闭抽屉 */
const handleClose = () => {
  visible.value = false
  emit('close')
}

defineExpose({
  open
})
</script>

<style lang="scss" scoped>
.flow-icon {
  display: flex;
  width: 38px;
  height: 38px;
  margin-right: 10px;
  background-color: var(--el-color-primary);
  border-radius: 0.25rem;
  align-items: center;
  justify-content: center;
}
.diagram {
  height: 520px;
}
</style>
